<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>骨质疏松健康管理平台 - Web 数据看板</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
        }

        header {
            background: white;
            padding: 30px;
            border-radius: 12px;
            margin-bottom: 30px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
        }

        h1 {
            color: #333;
            margin-bottom: 10px;
        }

        .status {
            display: inline-block;
            padding: 8px 16px;
            background: #4CAF50;
            color: white;
            border-radius: 20px;
            font-size: 14px;
        }

        .status.offline {
            background: #FF6B6B;
        }

        .grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }

        .card {
            background: white;
            border-radius: 12px;
            padding: 20px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }

        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);
        }

        .card h2 {
            color: #333;
            margin-bottom: 15px;
            font-size: 18px;
            border-bottom: 2px solid #4CAF50;
            padding-bottom: 10px;
        }

        .stat {
            margin-bottom: 12px;
            padding: 10px;
            background: #f5f5f5;
            border-radius: 8px;
        }

        .stat-label {
            font-size: 12px;
            color: #999;
            text-transform: uppercase;
        }

        .stat-value {
            font-size: 24px;
            font-weight: bold;
            color: #4CAF50;
            margin-top: 5px;
        }

        .list-item {
            padding: 10px 0;
            border-bottom: 1px solid #eee;
            font-size: 14px;
            color: #666;
        }

        .list-item:last-child {
            border-bottom: none;
        }

        .button-group {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            margin-bottom: 30px;
        }

        button {
            padding: 10px 20px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            transition: background 0.3s ease;
        }

        button:hover {
            background: #45a049;
        }

        button.secondary {
            background: #667eea;
        }

        button.secondary:hover {
            background: #5568d3;
        }

        .loading {
            text-align: center;
            padding: 20px;
            color: #999;
        }

        .error {
            background: #FFE0E0;
            color: #C00;
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
        }

        .success {
            background: #E0FFE0;
            color: #0A0;
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
        }

        .table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 15px;
        }

        .table th {
            background: #f5f5f5;
            padding: 10px;
            text-align: left;
            font-weight: 600;
            border-bottom: 2px solid #4CAF50;
        }

        .table td {
            padding: 10px;
            border-bottom: 1px solid #eee;
        }

        .badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 12px;
            font-weight: 600;
        }

        .badge.high {
            background: #FFE0E0;
            color: #C00;
        }

        .badge.medium {
            background: #FFFACD;
            color: #FF8C00;
        }

        .badge.low {
            background: #E0FFE0;
            color: #0A0;
        }

        @media (max-width: 768px) {
            .grid {
                grid-template-columns: 1fr;
            }

            header {
                padding: 20px;
            }

            .button-group {
                flex-direction: column;
            }

            button {
                width: 100%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>🏥 骨质疏松健康管理平台 - Web 数据看板</h1>
            <p style="color: #666; margin-top: 10px;">API 服务地址: <code>http://localhost:3000</code></p>
            <div id="connectionStatus" class="status">正在连接...</div>
        </header>

        <div class="button-group">
            <button onclick="loadAllData()">🔄 刷新所有数据</button>
            <button class="secondary" onclick="exportJSON()">📥 导出 JSON</button>
            <button class="secondary" onclick="clearCache()">🗑️ 清除缓存</button>
        </div>

        <div id="message"></div>

        <div class="grid">
            <!-- 用户信息卡片 -->
            <div class="card">
                <h2>👤 用户信息</h2>
                <div id="userInfo">
                    <div class="loading">加载中...</div>
                </div>
            </div>

            <!-- 最近运动记录 -->
            <div class="card">
                <h2>🏃 最近运动</h2>
                <div id="exerciseInfo">
                    <div class="loading">加载中...</div>
                </div>
            </div>

            <!-- 运动统计 -->
            <div class="card">
                <h2>📊 运动统计</h2>
                <div id="exerciseStats">
                    <div class="loading">加载中...</div>
                </div>
            </div>

            <!-- 用药依从性 -->
            <div class="card">
                <h2>💊 用药管理</h2>
                <div id="medicationInfo">
                    <div class="loading">加载中...</div>
                </div>
            </div>

            <!-- 骨密度检测 -->
            <div class="card">
                <h2>🦴 骨密度检测</h2>
                <div id="boneDensityInfo">
                    <div class="loading">加载中...</div>
                </div>
            </div>

            <!-- 问卷评分历史 -->
            <div class="card">
                <h2>📋 问卷评分历史</h2>
                <div id="questionnaireInfo">
                    <div class="loading">加载中...</div>
                </div>
            </div>
        </div>

        <!-- 详细数据表格 -->
        <div class="card">
            <h2>📈 运动记录详情</h2>
            <div id="exerciseTable">
                <div class="loading">加载中...</div>
            </div>
        </div>

        <div class="card">
            <h2>💊 用药提醒详情</h2>
            <div id="medicationTable">
                <div class="loading">加载中...</div>
            </div>
        </div>
    </div>

    <script>
        const API_URL = 'http://localhost:3000/api';

        // 内置演示用模拟数据（当接口不可用时回退到这些数据）
        const MOCK = {
            user: { id: 'user_001', name: '李华', age: 65, gender: '女', phone: '13800138000', email: 'lihua@example.com' },
            exerciseRecords: [
                { date: '2025-10-30', duration: 45, exercises: ['快走','太极拳'], calories: 280 },
                { date: '2025-10-29', duration: 30, exercises: ['拉伸','弹力带'], calories: 160 },
                { date: '2025-10-28', duration: 25, exercises: ['快走'], calories: 140 },
                { date: '2025-10-27', duration: 40, exercises: ['瑜伽'], calories: 220 },
                { date: '2025-10-26', duration: 35, exercises: ['上肢力量'], calories: 200 }
            ],
            statistics: {
                thisWeekExercise: { totalMinutes: 225, sessions: 5, calories: 1300 },
                thisMonthExercise: { totalMinutes: 850, sessions: 18, calories: 5200 },
                medicationAdherence: { completed: 8, missed: 2, adherenceRate: 80 },
                boneHealthStatus: { latestTScore: -1.8, latestDiagnosis: '骨量减少', trend: 'stable' }
            },
            medicationReminders: [
                { id: 'med_001', name: '钙片', type: 'medication', time: '08:00', frequency: 'daily', dosage: '2片', notes: '饭后30分钟服用', completedDates: ['2025-10-30','2025-10-29','2025-10-28'] },
                { id: 'med_002', name: '维生素D', type: 'nutrition', time: '12:00', frequency: 'daily', dosage: '1粒', notes: '', completedDates: ['2025-10-30','2025-10-28'] },
                { id: 'med_003', name: '阿仑膦酸钠', type: 'medication', time: '09:00', frequency: 'weekly', dosage: '70mg', notes: '', completedDates: ['2025-10-27'] }
            ],
            boneDensityHistory: [
                { date: '2025-10-27', type: 'DXA', tScore: -1.8, zScore: -0.5, diagnosis: '骨量减少' },
                { date: '2025-07-20', type: 'DXA', tScore: -2.1, zScore: -0.7, diagnosis: '骨量减少' },
                { date: '2025-04-15', type: 'DXA', tScore: -1.6, zScore: -0.3, diagnosis: '骨量减少' }
            ],
            questionnaireHistory: [
                { date: '2025-10-28', score: 12, riskLevel: '中' },
                { date: '2025-08-15', score: 8, riskLevel: '低' },
                { date: '2025-05-10', score: 16, riskLevel: '高' }
            ]
        };

        // 带回退的请求工具
        async function fetchJSON(path, fallbackData) {
            try {
                const response = await fetch(`${API_URL}${path}`);
                if (!response.ok) throw new Error(response.statusText);
                return await response.json();
            } catch (e) {
                // 统一返回结构以兼容现有渲染代码
                return { success: true, data: fallbackData, count: Array.isArray(fallbackData) ? fallbackData.length : undefined };
            }
        }

        // 初始化
        window.addEventListener('DOMContentLoaded', () => {
            loadAllData();
            setInterval(loadAllData, 30000); // 每30秒刷新一次
        });
        // 加载所有数据
        async function loadAllData() {
            try {
                await Promise.all([
                    loadUserInfo(),
                    loadExerciseInfo(),
                    loadExerciseStats(),
                    loadMedicationInfo(),
                    loadBoneDensityInfo(),
                    loadQuestionnaireInfo(),
                    loadExerciseTable(),
                    loadMedicationTable()
                ]);
                updateConnectionStatus(true);
                showMessage('数据加载成功！', 'success');
            } catch (error) {
                updateConnectionStatus(false);
                showMessage('数据加载失败: ' + error.message, 'error');
            }
        }

        // 获取用户信息
        async function loadUserInfo() {
            try {
                const result = await fetchJSON('/user', MOCK.user);
                const user = result.data;
                document.getElementById('userInfo').innerHTML = `
                    <div class="stat">
                        <div class="stat-label">姓名</div>
                        <div class="stat-value">${user.name}</div>
                    </div>
                    <div class="stat">
                        <div class="stat-label">年龄 / 性别</div>
                        <div class="stat-value">${user.age} 岁 / ${user.gender}</div>
                    </div>
                    <div class="list-item">📞 ${user.phone}</div>
                    <div class="list-item">📧 ${user.email}</div>
                `;
            } catch (error) {
                document.getElementById('userInfo').innerHTML = `<div class="error">加载失败</div>`;
            }
        }

        // 获取最近运动
        async function loadExerciseInfo() {
            try {
                const result = await fetchJSON('/exercise-records', MOCK.exerciseRecords);
                const exercises = (result.data || []).slice(0, 3);
                const html = exercises.map(ex => `
                    <div class="list-item">
                        <strong>${ex.date}</strong><br>
                        ⏱️ ${ex.duration}分钟 | 🔥 ${ex.calories}卡<br>
                        💪 ${Array.isArray(ex.exercises) ? ex.exercises.join(' • ') : ex.exercises}
                    </div>
                `).join('');
                document.getElementById('exerciseInfo').innerHTML = html || '<div class="loading">暂无数据</div>';
            } catch (error) {
                document.getElementById('exerciseInfo').innerHTML = `<div class="error">加载失败</div>`;
            }
        }

        // 获取运动统计
        async function loadExerciseStats() {
            try {
                const result = await fetchJSON('/statistics', MOCK.statistics);
                const stats = result.data;
                document.getElementById('exerciseStats').innerHTML = `
                    <div class="stat">
                        <div class="stat-label">本周运动</div>
                        <div class="stat-value">${stats.thisWeekExercise.totalMinutes}分钟</div>
                        <small>${stats.thisWeekExercise.sessions}次 | ${stats.thisWeekExercise.calories}卡</small>
                    </div>
                    <div class="stat">
                        <div class="stat-label">本月运动</div>
                        <div class="stat-value">${stats.thisMonthExercise.totalMinutes}分钟</div>
                        <small>${stats.thisMonthExercise.sessions}次 | ${stats.thisMonthExercise.calories}卡</small>
                    </div>
                `;
            } catch (error) {
                document.getElementById('exerciseStats').innerHTML = `<div class="error">加载失败</div>`;
            }
        }

        // 获取用药信息
        async function loadMedicationInfo() {
            try {
                const medsRes = await fetchJSON('/medication-reminders', MOCK.medicationReminders);
                const statsRes = await fetchJSON('/statistics', MOCK.statistics);
                const adherence = statsRes.data.medicationAdherence;
                const medications = medsRes.data.slice(0, 3);
                const html = medications.map(med => `
                    <div class="list-item">
                        <strong>${med.name}</strong><br>
                        ${med.time} • ${med.frequency} • ${med.dosage}
                    </div>
                `).join('');
                document.getElementById('medicationInfo').innerHTML = `
                    ${html}
                    <div class="stat">
                        <div class="stat-label">依从性</div>
                        <div class="stat-value">${adherence.adherenceRate}%</div>
                        <small>${adherence.completed}次完成 | ${adherence.missed}次遗漏</small>
                    </div>
                `;
            } catch (error) {
                document.getElementById('medicationInfo').innerHTML = `<div class="error">加载失败</div>`;
            }
        }

        // 获取骨密度信息
        async function loadBoneDensityInfo() {
            try {
                const result = await fetchJSON('/bone-density-history', MOCK.boneDensityHistory);
                const latest = result.data[0];
                document.getElementById('boneDensityInfo').innerHTML = `
                    <div class="stat">
                        <div class="stat-label">最新检测 (${latest.type})</div>
                        <div class="stat-value">${latest.date}</div>
                    </div>
                    <div class="list-item">
                        <strong>T值:</strong> ${latest.tScore.toFixed(2)}<br>
                        <strong>Z值:</strong> ${latest.zScore.toFixed(2)}<br>
                        <strong>诊断:</strong> <span class="badge ${latest.diagnosis === '骨量减少' ? 'medium' : 'low'}">${latest.diagnosis}</span>
                    </div>
                    <div class="list-item">
                        <small>更多记录: ${result.count || result.data.length} 条</small>
                    </div>
                `;
            } catch (error) {
                document.getElementById('boneDensityInfo').innerHTML = `<div class="error">加载失败</div>`;
            }
        }

        // 获取问卷信息
        async function loadQuestionnaireInfo() {
            try {
                const result = await fetchJSON('/questionnaire-history', MOCK.questionnaireHistory);
                const questionnaires = result.data.slice(0, 3);
                const html = questionnaires.map(q => `
                    <div class="list-item">
                        <strong>${q.date}</strong><br>
                        评分: ${q.score} | 风险: <span class="badge ${q.riskLevel === '高' ? 'high' : q.riskLevel === '中' ? 'medium' : 'low'}">${q.riskLevel}</span>
                    </div>
                `).join('');
                document.getElementById('questionnaireInfo').innerHTML = html || '<div class="loading">暂无数据</div>';
            } catch (error) {
                document.getElementById('questionnaireInfo').innerHTML = `<div class="error">加载失败</div>`;
            }
        }

        // 运动记录表格
        async function loadExerciseTable() {
            try {
                const result = await fetchJSON('/exercise-records', MOCK.exerciseRecords);
                const rows = result.data.map(ex => `
                    <tr>
                        <td>${ex.date}</td>
                        <td>${ex.duration}分钟</td>
                        <td>${Array.isArray(ex.exercises) ? ex.exercises.join(', ') : ex.exercises}</td>
                        <td>${ex.calories}卡</td>
                    </tr>
                `).join('');
                document.getElementById('exerciseTable').innerHTML = `
                    <table class="table">
                        <thead>
                            <tr>
                                <th>日期</th>
                                <th>时长</th>
                                <th>运动项目</th>
                                <th>消耗卡路里</th>
                            </tr>
                        </thead>
                        <tbody>${rows}</tbody>
                    </table>
                `;
            } catch (error) {
                document.getElementById('exerciseTable').innerHTML = `<div class="error">加载失败</div>`;
            }
        }

        // 用药提醒表格
        async function loadMedicationTable() {
            try {
                const result = await fetchJSON('/medication-reminders', MOCK.medicationReminders);
                const rows = result.data.map(med => `
                    <tr>
                        <td>${med.name}</td>
                        <td>${med.type === 'medication' ? '用药' : '营养'}</td>
                        <td>${med.time}</td>
                        <td>${med.dosage}</td>
                        <td>${med.completedDates.length}次</td>
                    </tr>
                `).join('');
                document.getElementById('medicationTable').innerHTML = `
                    <table class="table">
                        <thead>
                            <tr>
                                <th>名称</th>
                                <th>类型</th>
                                <th>时间</th>
                                <th>剂量</th>
                                <th>完成次数</th>
                            </tr>
                        </thead>
                        <tbody>${rows}</tbody>
                    </table>
                `;
            } catch (error) {
                document.getElementById('medicationTable').innerHTML = `<div class="error">加载失败</div>`;
            }
        }

        // 更新连接状态
        function updateConnectionStatus(connected) {
            const status = document.getElementById('connectionStatus');
            if (connected) {
                status.className = 'status';
                status.textContent = '✅ 已连接';
            } else {
                status.className = 'status offline';
                status.textContent = '❌ 未连接';
            }
        }

        // 显示消息
        function showMessage(text, type) {
            const messageDiv = document.getElementById('message');
            messageDiv.className = type;
            messageDiv.textContent = text;
            setTimeout(() => {
                messageDiv.textContent = '';
                messageDiv.className = '';
            }, 3000);
        }

        // 导出 JSON
        async function exportJSON() {
            try {
                const result = await fetchJSON('/all-data', {
                    user: MOCK.user,
                    questionnaireHistory: MOCK.questionnaireHistory,
                    boneDensityHistory: MOCK.boneDensityHistory,
                    exerciseRecords: MOCK.exerciseRecords,
                    medicationReminders: MOCK.medicationReminders,
                    statistics: MOCK.statistics
                });
                const dataStr = JSON.stringify(result.data, null, 2);
                const dataBlob = new Blob([dataStr], { type: 'application/json' });
                const url = URL.createObjectURL(dataBlob);
                const link = document.createElement('a');
                link.href = url;
                link.download = `health_data_${new Date().toISOString().split('T')[0]}.json`;
                link.click();
                showMessage('数据已导出！', 'success');
            } catch (error) {
                showMessage('导出失败: ' + error.message, 'error');
            }
        }

        // 清除缓存
        function clearCache() {
            localStorage.clear();
            sessionStorage.clear();
            showMessage('缓存已清除！', 'success');
        }
    </script>
</body>
</html>
